
package com.joysuch.wwyt;

import cn.zlg.common.datasafety.DataDeleteChecker;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.persistence.Table;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

//@Aspect
//@Configuration
public class DataSafetyCheckAop {

    private Logger logger = LoggerFactory.getLogger(DataSafetyCheckAop.class);
    @Autowired
    private DataDeleteChecker<Long> dataDeleteChecker;

    /**
     * 定义切入点，切入点为com.example.aop下的所有函数
     */
    @Pointcut("execution(public * com.joysuch.wwyt..service..*.delete*(Long))")
    public void deleteCheckById() {
        System.out.println("deleteCheckById()");
    }

    /**
     * 前置通知：在连接点之前执行的通知
     *
     * @param joinPoint
     * @throws Throwable
     */
    @Before("deleteCheckById()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String wholeMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();

        // System.out.println("deleteCheck()。doBefore");
        // // 记录下请求内容
        // System.out.println("CLASS_METHOD : " + wholeMethod);
        // System.out.println("CLASS_METHOD : " + joinPoint.getSignature().toLongString());
        // System.out.println("CLASS_METHOD : " + joinPoint.getSignature().toShortString());
        // System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));
        String tableName = parseTableNameFromServiceClass(joinPoint);
        dataDeleteChecker.check(tableName, (Long) joinPoint.getArgs()[0]);
        dataDeleteChecker.check(wholeMethod, (Long) joinPoint.getArgs()[0]);
    }

    private String parseTableNameFromServiceClass(JoinPoint joinPoint) {
        String name = findFromProperty(joinPoint.getSignature().getDeclaringType());
        if (name != null) {
            return name;
        }
        String simpleName = joinPoint.getSignature().getDeclaringType().getSimpleName();
        simpleName = "WWYT" + simpleName.replace("ServiceImpl", "").replaceAll("[A-Z]", "_$0");
        return simpleName.toUpperCase();
    }

    private String findFromProperty(Class declaringType) {
        try {
            // PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(declaringType, "dao");
            Field field = declaringType.getDeclaredField("dao");
            Class<?>[] interfaces = field.getType().getInterfaces();
            for (Class c : interfaces) {
                if (c == JpaRepository.class) {
                    Type[] types = field.getType().getGenericInterfaces();
                    Type type = ((ParameterizedType) types[0]).getActualTypeArguments()[0];
                    Table t = (Table) ((Class) type).getAnnotation(Table.class);
                    return t.name().toUpperCase();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @AfterReturning(returning = "ret", pointcut = "deleteCheckById()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求，返回内容
        logger.info("RESPONSE : " + ret);
    }
}
